package com.example.aigc_education.security.filter;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.example.aigc_education.common.BusinessException;
import com.example.aigc_education.constant.CacheConstants;
import com.example.aigc_education.security.handle.CustomAuthenticationFailureHandler;
import com.example.aigc_education.utils.RedisCache;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 手机验证码校验过滤器
 */
@Component
public class MobileCodeValidateFilter extends OncePerRequestFilter {

    private String codeParamter = "code";  // 前端输入的手机短信验证码参数名

    private String phoneParameter = "phone";  // 前端输入的手机号参数名

    // 自定义登录失败处理器
    @Resource
    private CustomAuthenticationFailureHandler customAuthenticationFailureHandler;

    @Resource
    private RedisCache redisCache;


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (StringUtils.isNotBlank(request.getParameter(codeParamter))) {
            try {
                validate(request);
            } catch (BusinessException e) {
                customAuthenticationFailureHandler.onAuthenticationFailure(request, response, null);
                e.printStackTrace();
                return;
            }
        }
        filterChain.doFilter(request, response);
    }

    /**
     * 检验用户输入的手机验证码的合法性
     */
    private void validate(HttpServletRequest request) {
        // 获取用户传入的手机验证码值
        String requestCode = request.getParameter(this.codeParamter);
        String phone = request.getParameter(phoneParameter);
        if(requestCode == null) {
            requestCode = "";
        }
        requestCode = requestCode.trim();

        String smsKey = CacheConstants.SMS_CODE_KEY + phone;
        // 获取 redis 中存储的手机短信验证码
        String savedCode = (String) redisCache.getCacheObject(smsKey);

        if (savedCode != null) {
            // 随手清除验证码，无论是失败，还是成功。客户端应在登录失败时刷新验证码
            boolean res = redisCache.deleteObject(smsKey);
            if (!res) {
                throw new BusinessException("验证码清除失败");
            }
        }

        // 校验出错，抛出异常
        if (StringUtils.isBlank(requestCode)) {
            throw new BusinessException("验证码的值不能为空");
        }
        if (savedCode == null) {
            throw new BusinessException("验证码不存在");
        }
        if (redisCache.isExpire(smsKey)) {
            throw new BusinessException("验证码过期");
        }
        if (!requestCode.equalsIgnoreCase(savedCode)) {
            throw new BusinessException("验证码输入错误");
        }
    }
}
